<template>
  <div class="pro-upload-list-container">
    <n-image-group>
      <n-data-table
        :columns="state.columns"
        :data="fileListData"
        v-bind="$attrs"
      />
    </n-image-group>
  </div>
</template>

<script lang="ts" setup name="ProUploadList">
  import { NButton, NImage, NTag, NProgress, DataTableColumn } from 'naive-ui'
  import { Transition } from 'vue'
  import mime from 'mime'
  import { transformSize } from '@/utils/file/file'
  import { FileInfo } from '../pro-upload/type'

  interface UploadListType {
    fileList: Array<FileInfo>
    defaultList?: Array<FileInfo>
    showCancelButton?: boolean
    showDeleteButton?: boolean
    showRetryButton?: boolean
    showDownloadButton?: boolean
    showPercentage?: boolean
    column?: Array<
      'thumbnail' | 'name' | 'type' | 'size' | 'status' | 'operate'
    >
  }

  const props = withDefaults(defineProps<UploadListType>(), {
    defaultList: () => [],
    showCancelButton: true,
    showDeleteButton: true,
    showRetryButton: true,
    showDownloadButton: true,
    showPercentage: true,
    column: () => ['thumbnail', 'name', 'type', 'size', 'status', 'operate']
  })

  // 状态列表
  enum StatusType {
    PENDING = 'pending',
    UPLOADING = 'uploading',
    FINISHED = 'finished',
    ERROR = 'error'
  }

  const statusOptions = [
    {
      status: StatusType.PENDING,
      type: 'info',
      text: '准备中',
      percentage: 'default'
    },
    {
      status: StatusType.UPLOADING,
      type: 'info',
      text: '上传中...',
      percentage: 'default'
    },
    {
      status: StatusType.FINISHED,
      type: 'success',
      text: '成功',
      percentage: 'success'
    },
    {
      status: StatusType.ERROR,
      type: 'error',
      text: '失败',
      percentage: 'error'
    }
  ]

  const state = reactive<{
    columns: DataTableColumn
    deletedFileIdList: Array<string>
  }>({
    columns: [
      props.column.includes('thumbnail') && {
        title: '缩略图',
        render: (row) => {
          return h(NImage, {
            width: 80,
            height: 40,
            src: row.thumbnailUrl
          })
        },
        align: 'center'
      },
      props.column.includes('name') && {
        title: '文件名',
        key: 'name',
        render: (row) => {
          return h('div', {}, [
            h(
              'div',
              {
                style: 'margin-bottom: 5px'
              },
              row.name
            ),
            props.showPercentage &&
              h(
                Transition,
                {
                  name: 'fade'
                },
                [
                  row.percentage !== 100 &&
                    row.status === StatusType.UPLOADING &&
                    h(
                      'div',
                      {
                        class: 'percentage-box'
                      },
                      [
                        h(NProgress, {
                          type: 'line',
                          percentage: row.percentage,
                          processing: row.percentage !== 100,
                          'show-indicator': false,
                          height: 2
                        })
                      ]
                    )
                ]
              )
          ])
        },
        align: 'center'
      },
      props.column.includes('type') && {
        title: '文件类型',
        render: (row) => {
          return mime.getExtension(row.type) || row.type
        },
        align: 'center'
      },
      props.column.includes('size') && {
        title: '文件大小',
        render: (row) => {
          console.log(row.size)

          return h('text', {}, transformSize(row.size) || '')
        },
        align: 'center'
      },
      props.column.includes('status') && {
        title: '状态',
        render: (row) => {
          const option = statusOptions.find((i) => i.status === row.status)
          return h(
            NTag,
            {
              style: {
                marginRight: '6px'
              },
              type: option && option.type,
              bordered: false
            },
            {
              default: () => option && option.text
            }
          )
        },
        align: 'center'
      },
      props.column.includes('operate') && {
        title: '操作',
        render: (row) => {
          // 取消
          const cancelEl =
            props.showCancelButton &&
            h(
              NButton,
              {
                quaternary: true,
                type: 'info',
                onClick: () => {
                  cancelFile(row)
                }
              },
              {
                default: () => '取消'
              }
            )
          // 删除
          const delEl =
            props.showDeleteButton &&
            h(
              NButton,
              {
                quaternary: true,
                type: 'error',
                onClick: () => {
                  deleteFile(row)
                }
              },
              {
                default: () => '删除'
              }
            )
          // 重新上传
          const resetEl =
            props.showRetryButton &&
            h(
              NButton,
              {
                quaternary: true,
                type: 'warning',
                onClick: () => {
                  retryFile(row)
                }
              },
              {
                default: () => '重新上传'
              }
            )
          const downloadEl =
            props.showDownloadButton &&
            h(
              NButton,
              {
                quaternary: true,
                type: 'info',
                onClick: () => {
                  downloadFile(row)
                }
              },
              {
                default: () => '下载'
              }
            )
          const operates = [
            [StatusType.UPLOADING].includes(row.status) ? cancelEl : delEl,
            row.status === StatusType.ERROR && resetEl,
            row.status === StatusType.FINISHED && downloadEl
          ]
          return h('div', {}, operates.filter(Boolean))
        },
        align: 'center'
      }
    ].filter(Boolean),
    deletedFileIdList: []
  })

  const emits = defineEmits(['delete', 'retry', 'cancel', 'download'])

  // 渲染表格的真实数据
  const fileListData = computed(() => {
    return [...props.defaultList, ...props.fileList].filter(
      (file) => !state.deletedFileIdList.includes(file.id)
    )
  })

  // 取消
  const cancelFile = (row: FileInfo) => {
    emits('cancel', row)
  }

  // 删除
  const deleteFile = (row: FileInfo) => {
    state.deletedFileIdList.push(row.id)
    emits('delete', row)
  }

  // 重新上传
  const retryFile = (row: FileInfo) => {
    emits('retry', row)
  }

  // 下载
  const downloadFile = (row: FileInfo) => {
    emits('download', row)
  }

  // 获取已成功上传文件列表
  const getSuccessFileList = (): Array<FileInfo> => {
    const fileList = fileListData.value.filter(
      (file) => file.status === StatusType.FINISHED
    )
    return fileList
  }
  // 获取全部上传文件列表
  const getAllFileList = (): Array<FileInfo> => {
    return unref(fileListData)
  }

  // 获取上传响应结果数据
  const getUploadResult = (): unknown[] => {
    return getSuccessFileList().map((file) => file.response)
  }

  // 判断是否上传完毕（列表中如果有正在上传或者有失败的文件，则返回false）
  const isAllDone = (): boolean => {
    return getAllFileList().length === getSuccessFileList().length
  }

  defineExpose({
    isAllDone,
    getUploadResult,
    getAllFileList,
    getSuccessFileList,
    deleteFile
  })
</script>

<style lang="less" scoped>
  .fade-leave-active,
  .fade-enter-active {
    transition: all 20s cubic-bezier(1, 0.5, 0.8, 1);
  }

  .fade-enter-from,
  .fade-leave-to {
    opacity: 0;
  }
</style>
